﻿/*
 * Twipler - Twitter Web Client with features.
 *  
 *  Copyright (C) 2009, 2010. Ian Quigley
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details. 
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Text;

using Twipler.App.Parse.Html.Consumers;
using Twipler.App.Render.Tree;

namespace Twipler.App.Parse.Html
{
    public class Template : StringParser
    {
        public const string StartMarker = "#!";
        public const string EndMarker = "!#";

        
        public Template(string content) : base(content) { }

        public AbstractItem Parse()
        {
            string waste = string.Empty;
            return ParseUntil(null, ref waste, null);
        }

        public AbstractItem ParseUntil(IEnumerable<string> tags, ref string tag, TemplateConsumer parent)
        {
            List<AbstractItem> list = new List<AbstractItem>();

            while (IsEmpty == false)
            {
                AddToOuptput(list, PlainHtmlItem.Create(ConsumeToEndOrMarker(StartMarker)));

                if (IsEmpty)
                    break;
                                
                string next = TextBeforeNext(true, EndMarker);
                if ((tags != null) && (tags.Contains(next)))
                {
                    tag = next;
                    break;
                }

                TemplateConsumer cons = ConsumerFactory.Create(next);
                if (cons == null)
                {
                    AddToOuptput(list, PlainHtmlItem.Create(StartMarker + next));
                    continue;
                }

                AbstractItem item = cons.Process(this, parent);
                AddToOuptput(list, item);

                if (item is ParseErrorItem)
                    break;
            }

            if (list.Count == 1)
                return list[0];
            
            return ContainerItem.Create(list);
        }

        private void AddToOuptput(List<AbstractItem> items, AbstractItem item)
        {
            if (item == null)
                return;

            // If adding a PlainHtmlItem after another one, join them together.
            if ((items.Count > 0) && (items[items.Count - 1] is PlainHtmlItem) && (item is PlainHtmlItem))
                ((PlainHtmlItem) items[items.Count - 1]).Join((PlainHtmlItem)item);
            else
                items.Add(item);
        }
    }
}